import * as XLSX from 'xlsx' //vue3需要import * as 引入，不然报错
import common from '/@/common/common'

/* eslint-disable no-unused-vars */
/*调用示例
exportExcel() {
      Excel.exportExcel(this.jsonData, "文件");
    },
importFile() {
      Excel.importExcel((data, dataRef) => {
        alert("数据已经打印在控制台");
        console.log(data);
        console.log(dataRef);
      });
    }

作者：FateOfKing
链接：https://juejin.cn/post/6844903944397783054
来源：稀土掘金
著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。
*/


// 接口类型和方法
interface BaseType{
    exportExcel(json: Array<Object>, name: string, head?: Object): void
    exportExcelAutoHead(json: Array<Object>, name: string, head?: Array<Array<string>>): void
    importExcel(callback: Function)
}

class Excel implements BaseType{
    /**
     * @description: 
     * @param {Object} json 服务端发过来的数据
     * @param {String} name 导出Excel文件名字
     * @param {Object} head 英文头转中文的json
     * @return: 
     */
    exportExcel(json: Array<Object>, name: string, head?: Object) {
        /* convert state to workbook */
        var data = new Array();
        var keyArray = new Array();

        for (const key1 in json) {
            if (json.hasOwnProperty(key1)) {
                let element = json[key1];
                var rowDataArray = new Array();
                for (const key2 in element) {
                    element = JSON.parse(JSON.stringify(element))
                    if (element.hasOwnProperty(key2)) {
                        const element2 = element[key2];
                        rowDataArray.push(element2);
                        if (keyArray.length < this.getLength(element)) {
                            keyArray.push(key2);
                        }
                    }
                }
                data.push(rowDataArray);
            }
        }
        if(common.objectAvailable(head)) {
            for(let key1 in keyArray){
                keyArray[key1] = head[keyArray[key1]]
            }
        }
        data.splice(0, 0, keyArray);
        const ws = XLSX.utils.aoa_to_sheet(data);
        const wb = XLSX.utils.book_new();
        XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
        /* generate file and send to client */
        XLSX.writeFile(wb, name + ".xlsx");
    }

    /**
     * @description: 
     * @param {Object} json 服务端发过来的数据
     * @param {String} name 导出Excel文件名字
     * @param {Array<string>} head 自定义头部的Array
     * @return: 
     */
     exportExcelAutoHead(json: Array<Object>, name: string, heads?: Array<Array<string>>) {
        /* convert state to workbook */
        var data = new Array();

        for (const key1 in json) {
            if (json.hasOwnProperty(key1)) {
                let element = json[key1];
                var rowDataArray = new Array();
                for (const key2 in element) {
                    element = JSON.parse(JSON.stringify(element))
                    if (element.hasOwnProperty(key2)) {
                        const element2 = element[key2];
                        rowDataArray.push(element2);
                    }
                }
                data.push(rowDataArray);
            }
        }
        for (let i in heads){
            data.splice(0, 0, heads[i])
        }
        const ws = XLSX.utils.aoa_to_sheet(data);
        const wb = XLSX.utils.book_new();
        XLSX.utils.book_append_sheet(wb, ws, "SheetJS");
        /* generate file and send to client */
        XLSX.writeFile(wb, name + ".xlsx");
    }


    /**
     * @description: 导入excel文件并返回数据
     * @param {function} 回调函数参数data,dataRef,一个是数据，一个是exce表单的索引 
     * @return: 
     */
    importExcel(callback) {
        var inputObj = document.createElement('input')
        inputObj.setAttribute('id', 'file');
        inputObj.setAttribute('type', 'file');
        inputObj.setAttribute('name', 'file');
        inputObj.setAttribute("style", 'visibility:hidden');
        inputObj.setAttribute("accept", ".xlsx,.xls,.csv")
        inputObj.addEventListener('change', (evt) => {
            const target = evt.target as HTMLInputElement;
            const files = target.files;
            if (files && files[0]) this._file(files[0], (data, dataRef) => {
                callback(data, dataRef)
            });
        })
        document.body.appendChild(inputObj);
        inputObj.value;
        inputObj.click();

    }

    /**
     * @description: 处理文件
     * @param {Object} file 文件对象
     * @param {function} callback 回调函数 
     * @return: 
     */
    _file(file, callback) {
        const make_cols = refstr => Array(XLSX.utils.decode_range(refstr).e.c + 1).fill(0).map((x, i) => ({
            name: XLSX.utils.encode_col(i),
            key: i
        }));

        /* Boilerplate to set up FileReader */
        const reader = new FileReader();
        reader.onload = (e) => {
            /* Parse data */
            const bstr = e.target.result;
            const wb = XLSX.read(bstr, {
                type: 'binary'
            });
            /* Get first worksheet */
            const wsname = wb.SheetNames[0];
            const ws = wb.Sheets[wsname];
            /* Convert array of arrays */
            const data = XLSX.utils.sheet_to_json(ws, {
                header: 1
            });
            /* Update state */
            callback(data, make_cols(ws['!ref']))

        };
        reader.readAsBinaryString(file);
    }

    /**
     * @description: 获取map的长度
     * @param {Object} obj map对象 
     * @return: map的长度
     */
    getLength(obj) {

        var count = 0;
        for (var i in obj) {

            if (obj.hasOwnProperty(i)) {
                count++;

            }
        }
        return count;
    }
}

const excel = new Excel()
export default excel;